//
//  MPCButton+YYWebImage.m
//  Pods
//
//  Created by jiaxuzhou on 2017/7/26.
//
//

#import "MPCButton+YYWebImage.h"
#import <objc/runtime.h>

#if MPT_USE_SDWebImageSwitch

#else

#import <YYWebImage/_YYWebImageSetter.h>

/// 保存YYIMage 缓存图片的对象 _YYWebImageSetter
static NSString *YYWebImageSetterKey = @"YYWebImageSetterKey";

static int32_t sentinelYY;

#endif

@implementation MPCButton (YYWebImage)

#if MPT_USE_SDWebImageSwitch

#else

- (void)yy_cancelCurrentImageLoadWithURL:(NSURL *)url
{
    _YYWebImageSetter *setter = [self yy_GetSetter];
    sentinelYY = [setter cancelWithNewURL:url];
}

- (UIImage *)yy_getCatcheMemoryImageWithImageURL:(NSURL *)imgUrl options:(MPWebImageOptions)options
{
    YYWebImageManager *manager = [YYWebImageManager sharedManager];
    UIImage *imageFromMemory = nil;
    if (manager.cache &&
        !(options & MPWebImageOption_UseNSURLCache) &&
        !(options & MPWebImageOption_RefreshImageCache))
    {
        imageFromMemory = [manager.cache getImageForKey:[manager cacheKeyForURL:imgUrl] withType:YYImageCacheTypeMemory];
        
        
        if (imageFromMemory)
        {
            if (!(options & MPWebImageOption_AvoidSetImage))
            {
                if (self.isSetBgImg) /// 判断是设置成背景图片还是普通图片
                {
                    [self setBackgroundImage:imageFromMemory forState:UIControlStateNormal];
                }
                else
                {
                    [self setImage:imageFromMemory forState:UIControlStateNormal];
                }
            }
            
            return imageFromMemory;
        }
    }
    
    return nil;
}

- (void)yy_getCatcheDiskImageWithImageURL:(NSURL *)imgUrl options:(MPWebImageOptions)options finish:(void (^)(UIImage *image))finish
{
    YYWebImageManager *manager = [YYWebImageManager sharedManager];
    if (manager.cache &&
        !(options & MPWebImageOption_UseNSURLCache) &&
        !(options & MPWebImageOption_RefreshImageCache))
    {
        dispatch_async([[self class] mp_setterQueue], ^{
            
            UIImage *imageFromDisk = [manager.cache getImageForKey:[manager cacheKeyForURL:imgUrl] withType:YYImageCacheTypeMemory];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                
                if (imageFromDisk)
                {
                    if (!(options & MPWebImageOption_AvoidSetImage))
                    {
                        
                        if (self.isSetBgImg) /// 判断是设置成背景图片还是普通图片
                        {
                            [self setBackgroundImage:imageFromDisk forState:UIControlStateNormal];
                        }
                        else
                        {
                            [self setImage:imageFromDisk forState:UIControlStateNormal];
                        }
                    }
                    
                    finish(imageFromDisk);
                }
                else
                {
                    finish(nil);
                }
            });
        });
    }
}

- (void)yy_downImageWithImageURL:(NSURL *)imgUrl
                         options:(MPWebImageOptions)options
                        progress:(MPWebImageDownloaderProgressBlock)progressBlock
                         success:(nullable MPWebImageSuccessBlock)success
                            fail:(nullable MPWebImageFailBlock)fail
{
    _yy_dispatch_sync_on_main_queue(^{
        
        YYWebImageManager *manager = [YYWebImageManager sharedManager];
        
        __weak typeof(self) _self = self;
        dispatch_async([_YYWebImageSetter setterQueue], ^{
            YYWebImageProgressBlock _progress = nil;
            if (progressBlock) _progress = ^(NSInteger receivedSize, NSInteger expectedSize) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    progressBlock(receivedSize, expectedSize,imgUrl);
                });
            };
            
            _YYWebImageSetter *setter = [self yy_GetSetter];
            [self yy_cancelCurrentImageLoadWithURL:imgUrl];

            __block int32_t newSentinel = 0;
            
            __block __weak typeof(setter) weakSetter = nil;
            YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error)
            {
                __strong typeof(_self) self = _self;
                BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage);
                dispatch_async(dispatch_get_main_queue(), ^
                               {
                                   BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel;
                                   if (!self)
                                   {
                                       return;
                                   }
                                   
                                   if (setImage && !sentinelChanged && !error)
                                   {
                                       
                                       /// 处理动画和图片校验
                                       if ([self respondsToSelector:@selector(didFinishWithImage:)])
                                       {
                                           [self performSelector:@selector(didFinishWithImage:) withObject:image];
                                       }
                                       else
                                       {
                                           CATransition *transition = [CATransition animation];
                                           transition.duration = 0.2;
                                           transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
                                           transition.type = kCATransitionFade;
                                           [self.layer addAnimation:transition forKey:MPWebImageFadeAnimationKey];
                                           
                                           if (self.isSetBgImg) /// 判断是设置成背景图片还是普通图片
                                           {
                                               [self setBackgroundImage:image forState:UIControlStateNormal];
                                           }
                                           else
                                           {
                                               [self setImage:image forState:UIControlStateNormal];
                                           }
                                       }

                                   }
                                   
                                   if (image && stage == YYWebImageStageFinished && !error)
                                   {
                                       if (success)
                                       {
                                           success(image,url,[[self class] yy_getMPImageCacheType:from],[[self class] yy_getMPImageState:stage]);
                                       }
                                   }
                                   
                                   if (error)
                                   {
                                       if ([self respondsToSelector:@selector(didFailWithError:)])
                                       {
                                           [self performSelector:@selector(didFailWithError:) withObject:error];
                                       }
                                       
                                       if (fail)
                                       {
                                           fail(url, [[self class] yy_getMPImageCacheType:from] ,[[self class] yy_getMPImageState:stage],error);
                                       }
                                   }
                               });
            };
            
            newSentinel = [setter setOperationWithSentinel:sentinelYY url:imgUrl options:[[self class] yy_getYYImageOptions:options] manager:manager progress:_progress transform:nil completion:_completion];
            weakSetter = setter;
        });
    });
}

- (_YYWebImageSetter *)yy_GetSetter
{
    _YYWebImageSetter *setter = objc_getAssociatedObject(self,&YYWebImageSetterKey);
    if (!setter) {
        setter = [_YYWebImageSetter new];
        objc_setAssociatedObject(self, &YYWebImageSetterKey, setter, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return setter;
}

+ (MPWebImageFromType)yy_getMPImageCacheType:(YYWebImageFromType)cacheType
{
    MPWebImageFromType sdCacheState = [[[self dicYYImageCacheType] objectForKey:@(cacheType)] integerValue];
    
    return sdCacheState;
}

+ (MPWebImageStage)yy_getMPImageState:(YYWebImageStage)state
{
    MPWebImageStage yyState = [[[self dicYYImageStage] objectForKey:@(state)] integerValue];
    
    return yyState;
}

+ (YYWebImageOptions)yy_getYYImageOptions:(MPWebImageOptions)option
{
    YYWebImageOptions op = [[[self dicYYWebImageOptions] objectForKey:@(option)] integerValue];
    
    return op;
}

+ (NSDictionary *)dicYYImageCacheType
{
    return @{
             @(YYWebImageFromNone):@(MPWebImageCacheFromType_None),
             @(YYWebImageFromMemoryCacheFast):@(MPWebImageFromType_Memory),
             @(YYWebImageFromMemoryCache):@(MPWebImageFromType_Memory),
             @(YYWebImageFromDiskCache):@(MPWebImageFromType_Disk),
             @(YYWebImageFromRemote):@(MPWebImageFromType_Disk)
             
             };
}

+ (NSDictionary *)dicYYImageStage
{
    return @{
             @(YYWebImageStageProgress):@(MPWebImageStage_Progress),
             @(YYWebImageStageCancelled):@(MPWebImageStage_Cancelled),
             @(YYWebImageStageFinished):@(MPWebImageStage_Finished)
             };
}

+ (NSDictionary *)dicYYWebImageOptions
{
    return @{
             @(MPWebImageOption_ShowNetworkActivity):@(YYWebImageOptionShowNetworkActivity),
             @(MPWebImageOption_Progressive):@(YYWebImageOptionProgressive),
             @(MPWebImageOption_ProgressiveBlur):@(YYWebImageOptionProgressiveBlur),
             @(MPWebImageOption_UseNSURLCache):@(YYWebImageOptionUseNSURLCache),
             @(MPWebImageOption_AllowInvalidSSLCertificates):@(YYWebImageOptionAllowInvalidSSLCertificates),
             @(MPWebImageOption_AllowBackgroundTask):@(YYWebImageOptionAllowBackgroundTask),
             @(MPWebImageOption_HandleCookies):@(YYWebImageOptionHandleCookies),
             @(MPWebImageOption_RefreshImageCache):@(YYWebImageOptionRefreshImageCache),
             @(MPWebImageOption_IgnoreDiskCache):@(YYWebImageOptionIgnoreDiskCache),
             @(MPWebImageOption_IgnorePlaceHolder):@(YYWebImageOptionIgnorePlaceHolder),
             @(MPWebImageOption_IgnoreImageDecoding):@(YYWebImageOptionIgnoreImageDecoding),
             @(MPWebImageOption_IgnoreAnimatedImage):@(YYWebImageOptionIgnoreAnimatedImage),
             @(MPWebImageOption_SetImageWithFadeAnimation):@(YYWebImageOptionSetImageWithFadeAnimation),
             @(MPWebImageOption_AvoidSetImage):@(YYWebImageOptionAvoidSetImage),
             @(MPWebImageOption_IgnoreFailedURL):@(YYWebImageOptionIgnoreFailedURL),
             };
}

+ (void)yy_clearCatcheDisk:(void (^)())completion
{
    [[YYImageCache sharedCache].diskCache removeAllObjectsWithBlock:^
     {
         if (completion)
         {
             completion();
         }
     }];
}

+ (void)yy_clearCatcheMemory
{
    [[YYImageCache sharedCache].memoryCache removeAllObjects];
}



#endif

@end
